﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace game
{
    public class SceneFactory
    {
        public static Scene CreateScene(ContentManager contentMgr)
        {
            int layerNum = 3;

            Scene scene = new Scene();
            for (int i = 0; i < layerNum; i++)
            {
                scene.Layers.Add(new Layer(scene, i, i * 30000));
            }


            Random r = ShooterGame.Instance.Random;


            ModelUnit model3 = new ModelUnit(contentMgr.Load<Model>("Models\\Skybox"),
                Matrix.CreateScale(100000));


            //MeteorPlane meteorPlane = new MeteorPlane(scene, 2);
            //scene.Layers[2].GameObjects.Add(meteorPlane);

            Ship playerShip = CreateShips(scene, contentMgr, layerNum);

            CreateAsteroids(scene, contentMgr, layerNum);

            CreateCameras(scene, contentMgr, playerShip);

            SpaceBox objSky = new SpaceBox(scene, model3, 0);
            scene.SpaceBox = objSky;
            objSky.HookOn(playerShip);


            scene.planet1 = new Billboard(scene);
            scene.planet1.Position = new Vector3(-5000000, -10000, -6000000);
            scene.planet1.SetTexture("Textures\\planets\\pl3");
            scene.planet1.SetSize(4000000, 4000000);
            scene.planet1.Blending = Billboard.BlendingMode.REPLACE;

            scene.planet2 = new Billboard(scene);
            scene.planet2.Position = new Vector3(6000000, -10000, -1000000);
            scene.planet2.SetTexture("Textures\\planets\\pl4");
            scene.planet2.SetSize(500000, 500000);
            scene.planet2.Blending = Billboard.BlendingMode.REPLACE;

            scene.planet3 = new Billboard(scene);
            scene.planet3.Position = new Vector3(5000000, -10000, 6000000);
            scene.planet3.SetTexture("Textures\\planets\\pl1");
            scene.planet3.SetSize(4000000, 4000000);
            scene.planet3.Blending = Billboard.BlendingMode.REPLACE;

            scene.cloud = new Billboard(scene);
            scene.cloud.Position = new Vector3(60000, -10000, -10000);
            scene.cloud.SetTexture("Textures\\cloud1");
            scene.cloud.SetSize(500000, 500000);
            scene.cloud.Blending = Billboard.BlendingMode.ADDITIVE;

            return scene;
        }

        private static Ship CreateShips(Scene scene, ContentManager contentMgr, int layerNum)
        {
            scene.Armies = new List<Army>();
            scene.Armies.Add(new Army(0, Color.Green, new List<Squadron>()));
            scene.Armies.Add(new Army(1, Color.Red, new List<Squadron>()));
            scene.Armies[0].SquadronList.Add(new Squadron(scene.Armies[0], new List<Ship>()));
            scene.Armies[1].SquadronList.Add(new Squadron(scene.Armies[1], new List<Ship>()));

            ModelUnit model = new ModelUnit(contentMgr.Load<Model>("Models\\ship-red"), Matrix.CreateScale(5f));
            model.GlowTexture = contentMgr.Load<Texture>("Textures\\sf-01_glow");
            model.SetNormalMapping(contentMgr.Load<Texture2D>("Textures\\sf-01_normal"));
            Material m = new Material();
            m.Specular = new Vector3(1.0f);
            m.Alpha = 1.0f;
            m.Diffuse = new Vector3(1.0f, 1.0f, 1.0f);
            m.Ambient = m.Diffuse;
            m.SpecPower = 16;
            model.SetMaterial(m);

            ModelUnit mine = new ModelUnit(contentMgr.Load<Model>("Models\\mine"),
                Matrix.CreateScale(30f));

            ModelUnit model5 = new ModelUnit(contentMgr.Load<Model>("Models\\Ship_06"),
                Matrix.CreateRotationY((float)-MathHelper.Pi) * Matrix.CreateScale(300));
            model5.GlowTexture = contentMgr.Load<Texture>("Textures\\Ship_06_glow");
            model5.SetNormalMapping(contentMgr.Load<Texture2D>("Textures\\Ship_06_normal"));
            model5.SetMaterial(m);

            contentMgr.Load<Model>("Models\\rocket");

            for (int i = 0; i < layerNum; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                    Vector3 position = new Vector3(
                        -RandomHelper.Random.Next(280000),
                        scene.Layers[i].Height,
                        -RandomHelper.Random.Next(280000));

                    Fighter ship = new AIFighter(scene, model,
                                    i, position, scene.Armies[0].SquadronList[0]);
                    scene.Armies[0].SquadronList[0].ShipList.Add(ship);
                    scene.AddObject(ship, i);
                }
            }

            for (int i = 0; i < layerNum; i++)
            {
                for (int j = 0; j < 4; j++)
                {
                    Vector3 position = new Vector3(
                        RandomHelper.Random.Next(280000),
                        scene.Layers[i].Height,
                        RandomHelper.Random.Next(280000));

                    Fighter ship = new AIFighter(scene, model5,
                                    i, position, scene.Armies[1].SquadronList[0]);
                    scene.Armies[1].SquadronList[0].ShipList.Add(ship);
                    scene.AddObject(ship, i);
                }
            }


            PlayerFighter playerShip = new PlayerFighter(scene, model, 1, new Vector3(-125000, scene.Layers[1].Height, -125000), scene.Armies[0].SquadronList[0]);
            playerShip.Rotation = new Vector3(0, MathHelper.Pi * 1.25f, 0);
            scene.AddObject(playerShip, 1);

            scene.PlayerObject = playerShip;

            return playerShip;
        }


        private static void CreateCameras(Scene scene, ContentManager contentMgr, Ship playerShip)
        {
            HookCamera camera = new HookCamera(new Vector3(0.0f, 0.0f, 5000.0f), Vector3.Zero, Vector3.Up,
                45.0f, 4000.0f, 30000000.0f, ShooterGame.Instance.GraphicsDevice.Viewport.AspectRatio,
                new Vector3(0, -5000, -10000), Matrix.Identity);
            camera.HookOn(playerShip);
            scene.ActiveCamera = camera;

            //FreeCamera ccamera = new FreeCamera(new Vector3(0.0f, 60000.0f, 5000.0f), Vector3.Zero, Vector3.Up,
            //   45.0f, 4000.0f, 30000000.0f, ShooterGame.Instance.GraphicsDevice.Viewport.AspectRatio);
            //scene.ActiveCamera = ccamera;
        }


        private static void CreateAsteroids(Scene scene, ContentManager contentMgr, int layerNum)
        {
            int astNum = 5;
            ModelUnit[] asteroids = new ModelUnit[astNum];
            Material material = new Material();
            material.Specular = new Vector3(0.3f);
            material.SpecPower = 8;
            material.Alpha = 1.0f;
            material.Diffuse = new Vector3(1.0f, 1.0f, 1.0f);
            material.Ambient = material.Diffuse;
            for (int i = 0; i < astNum; i++)
            {
                asteroids[i] = new ModelUnit(contentMgr.Load<Model>("Models\\Asteroids\\ast" + (i+1).ToString()));
                asteroids[i].SetDiffuseMapping(ShooterGame.Instance.Content.Load<Texture2D>("Textures\\Asteroids\\1160"));
                asteroids[i].SetNormalMapping(
                    ShooterGame.Instance.Content.Load<Texture2D>("Textures\\Asteroids\\1160-normal"));
                asteroids[i].SetMaterial(material);
            }
            //asteroids[4] = new ModelUnit(contentMgr.Load<Model>("Models\\Tests\\capital"));
            //asteroids[4].SetDiffuseMapping(ShooterGame.Instance.Content.Load<Texture2D>("Models\\Tests\\piratehull1"));
            //asteroids[4].SetMaterial(material);
            

            //for (int i = 0; i < layerNum; i++)
            {
                for (int j = 0; j < 100; j++)
                {
                    Vector3 position = new Vector3(0, scene.Layers[1].Height, 0) + RandomHelper.RandomVector()
                        * (float)RandomHelper.Random.NextDouble() * 300000;
                    int index;
                    if (position.Y < ((scene.Layers[0].Height + scene.Layers[1].Height) / 2))
                        index = 0;
                    else if (position.Y < ((scene.Layers[1].Height + scene.Layers[2].Height) / 2))
                        index = 1;
                    else
                        index = 2;

                    int modelIndex = RandomHelper.Random.Next(5);
                    Asteroid obj = new Asteroid(scene, asteroids[modelIndex], position, index);
                    obj.SetSize(ShooterGame.Instance.Random.Next(90) + 40);
                    scene.AddObject(obj, index);
                }
            }

            //{
            //    Vector3 position = new Vector3(
            //                0,
            //                scene.Layers[1].Height,
            //                0);
            //    Asteroid obj = new Asteroid(scene, model2, position, 0);
            //    obj.SetSize(500);
            //    obj.SetMultiLayer(0, 2);
            //    obj.SetStatic();
            //    scene.AddObject(obj, 0, 2);
            //}
        }
    }
}
